package br.com.stimuli.loading.loadingtypes {

    import br.com.stimuli.loading.BulkLoader;
    
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.system.ApplicationDomain;
    import flash.system.LoaderContext;
    import flash.system.SecurityDomain;
    import flash.utils.*;

    /** @private */
    public class ImageItem extends LoadingItem {

        public var loader : Loader;
		
        public function ImageItem(url : URLRequest, type : String, uid : String){
            specificAvailableProps = [BulkLoader.CONTEXT];
            super(url, type, uid);
        }

        override public function _parseOptions(props : Object)  : Array{
            _context = props[BulkLoader.CONTEXT] || null;

            return super._parseOptions(props);
        }

        override public function load() : void{
            super.load();
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressHandler, false, 0, true);
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler, false, 0, true);
            loader.contentLoaderInfo.addEventListener(Event.INIT, onInitHandler, false, 0, true);
            loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onErrorHandler, false, 100, true);
            loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityErrorHandler, false, 0, true);
            loader.contentLoaderInfo.addEventListener(Event.OPEN, onStartedHandler, false, 0, true);  
            loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, super.onHttpStatusHandler, false, 0, true);
            try{
                // TODO: test for security error thown.
//				var lc:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, SecurityDomain.currentDomain);
				var lc:LoaderContext = new LoaderContext(false, new ApplicationDomain(ApplicationDomain.currentDomain.parentDomain), SecurityDomain.currentDomain); //avoids some security sandbox headaches that plague many users.
                loader.load(url, lc);
            }catch( e : SecurityError){
				try{
					loader.load(url);
				}catch(e:*){
                	onSecurityErrorHandler(_createErrorEvent(e));
				}
            }

        };

        public function _onHttpStatusHandler(evt : HTTPStatusEvent) : void{
            _httpStatus = evt.status;
            dispatchEvent(evt);
        }

        override public function onErrorHandler(evt : ErrorEvent) : void{
            super.onErrorHandler(evt);
        }

        public function onInitHandler(evt : Event) :void{
            dispatchEvent(evt);
        }

        override public function onCompleteHandler(evt : Event) : void {
            // TODO: test for the different behaviour when loading items with 
            // the a specific crossdomain and without one
            try{
                // of no crossdomain has allowed this operation, this might
                // raise a security error
                _content = loader.content;
				swfContent = loader.content;
				applicationDomain = LoaderInfo(evt.target).applicationDomain;
				super.onCompleteHandler(evt);
            }catch(e : SecurityError){
                // we can still use the Loader object (no dice for accessing it as data
                // though. Oh boy:
                _content = loader;
                super.onCompleteHandler(evt);
                // I am really unsure whether I should throw this event
                // it would be nice, but simply delegating the error handling to user's code 
                // seems cleaner (and it also mimics the Standar API behaviour on this respect)
                //onSecurityErrorHandler(e);
            }

        };

        override public function stop() : void{
            try{
                if(loader){
                    loader.close();
                }
            }catch(e : Error){

            }
            super.stop();
        };

        /** Gets a  definition from a fully qualified path (can be a Class, function or namespace). 
          @param className The fully qualified class name as a string.
          @return The definition object with that name or null of not found.
         */
        public function getDefinitionByName(className : String) : Object{
            if (loader.contentLoaderInfo.applicationDomain.hasDefinition(className)){
                return loader.contentLoaderInfo.applicationDomain.getDefinition(className);
            }
            return null;
        }

        override public function cleanListeners() : void {
            if (loader){
                var removalTarget : Object = loader.contentLoaderInfo;
                removalTarget.removeEventListener(ProgressEvent.PROGRESS, onProgressHandler, false);
                removalTarget.removeEventListener(Event.COMPLETE, onCompleteHandler, false);
                removalTarget.removeEventListener(Event.INIT, onInitHandler, false);
                removalTarget.removeEventListener(IOErrorEvent.IO_ERROR, onErrorHandler, false);
                removalTarget.removeEventListener(BulkLoader.OPEN, onStartedHandler, false);
                removalTarget.removeEventListener(HTTPStatusEvent.HTTP_STATUS, super.onHttpStatusHandler, false);
            }

        }

        override public function isImage(): Boolean{
            return (type == BulkLoader.TYPE_IMAGE);
        }

        override public function isSWF(): Boolean{
            return (type == BulkLoader.TYPE_MOVIECLIP);
        }

        override public function destroy() : void{
            stop();
            cleanListeners();
            _content = null;
            // this is an player 10 only feature. as such we must check it's existence
            // with the array acessor, or else the compiler will barf on player 9
            if (loader["unloadAndStop"] && loader["unloadAndStop"]) {
                loader["unloadAndStop"](true);
            }else if (loader["unload"] && loader["unload"] is Function) {
                // this is an air only feature. as such we must check it's existence
                // with the array acessor, or else the compiler will barf on non air projects
                loader["unload"]();
            }


            loader = null;
        }
        
        /****/
public var swfContent:Object;

private var applicationDomain:ApplicationDomain;

override public function getDefinition(pClassDefinition:String):*
{
	try
	{
		var _c:Class = applicationDomain.getDefinition(pClassDefinition) as Class;
		return new _c();
	}
	catch (err:Error)
	{
		return null;
	}
}

    }}
